module OpenAccount
    
    # mix this class into a user controller to get login functionality
    module OpenSessionController
        
        
        def new
            render
        end

        def create
            if using_open_id?
                begin
                    open_id_authentication
                rescue ActiveRecord::RecordInvalid => error
                    # validation failed
                    failed_login('Sorry could not log in with identity URL.  It is possible that your login or email is already in use.  If you already have an account, log into your account and then associate your Open ID with that account.')
                end
            else
                password_authentication(params[:login], params[:password])
            end
        end

        def destroy
            self.current_user.forget_me if logged_in?
            cookies.delete :auth_token
            reset_session
            flash[:notice] = "You have been logged out."
            redirect_back_or_default('/')
        end

        protected

        def password_authentication(login, password)
            
            self.current_user = User.authenticate(login, password)
            if logged_in?
                if params[:remember_me] == "1"
                    self.current_user.remember_me
                    cookies[:auth_token] = { :value => self.current_user.remember_token , :expires => self.current_user.remember_token_expires_at }
                end
                successful_login(self.current_user)
            else
                failed_login('Invalid login or password')
            end
        end

        def open_id_authentication
            # Pass optional :required and :optional keys to specify what sreg fields you want.
            # Be sure to yield registration, a third argument in the #authenticate_with_open_id block.
            authenticate_with_open_id(params[:openid_url], :required => [ :nickname, :email ]) do |result, identity_url, registration|
                new_user = false
                if result.successful?
                    if !@user = User.find_by_identity_url(identity_url)
                        new_user = true
                        @user = User.new(:identity_url => identity_url)
                        assign_registration_attributes!(registration)
                    end
                    self.current_user = @user
                    successful_login(new_user)
                else
                    failed_login(result.message || "Sorry could not log in with identity URL: #{identity_url}")
                end
            end
        end

        # registration is a hash containing the valid sreg keys given above
        # use this to map them to fields of your user model
        def assign_registration_attributes!(registration)
            { :login => 'nickname', :email => 'email' }.each do |model_attribute, registration_attribute|
                unless registration[registration_attribute].blank?
                    @user.send("#{model_attribute}=", registration[registration_attribute])
                end
            end
            @user.login = @user.identity_url unless @user.login.length > 0
            @user.save!
        end

        private

        def successful_login(new_user)
            logger.info "sucessful login for #{self.current_user.login}"
            redirect_back_or_default({:controller => 'users', :action => 'show', :id => self.current_user})
            flash[:notice] = "#{self.current_user.login} Logged in successfully"
            if new_user
                send_welcome
            end
        end

        def failed_login(message)
            logger.info message
            flash[:notice] = message
            respond_to do |format|
                format.html { render :action => "new" }
                format.xml { render :xml => @user.errors.to_xml }
            end
        end

        def send_welcome
            begin
                email = UserNotify.create_welcome(@user)
                UserNotify.deliver(email)
            rescue Exception => e
                logger.error 'Unable to send confirmation E-Mail:'
                logger.error e
            end
        end
        
    end
    
end